/*!
 * \file Desigualdad.cpp
 *
 * \date Aug 14, 2014
 * \author correa
 */

#include <Desigualdad.h>
#include <RDCliquer.h>

Desigualdad::Desigualdad(int nv, int nx) : _isRank(true)
{
	if (nx > 0)
		_coef = new IntValueArray(nx);
	else
		_coef = NULL;
	if (nv > 0)
		_soporte = new VertexSet(nv);
	else
		_soporte = NULL;
}

Desigualdad::Desigualdad(const Desigualdad& otra) : _isRank(otra._isRank)
{
	if (otra._soporte != NULL) {
		_soporte = new VertexSet(otra._soporte->capacity());
		_soporte->copyAll(*otra._soporte);
	}
	else
		_soporte = NULL;
	if (otra._coef != NULL) {
		_coef = new IntValueArray(otra._coef->capacity());
		_coef->copy(*otra._coef);
	}
	else
		_coef = NULL;
}

Desigualdad::Desigualdad(const Desigualdad&& otra) : _isRank(otra._isRank)
{
	if (otra._soporte != NULL) {
		_soporte = new VertexSet(otra._soporte->capacity());
		_soporte->copyAll(*otra._soporte);
	}
	else
		_soporte = NULL;
	if (otra._coef != NULL) {
		_coef = new IntValueArray(otra._coef->capacity());
		_coef->copy(*otra._coef);
	}
	else
		_coef = NULL;
}

Desigualdad::~Desigualdad()
{
	delete _soporte;
	delete _coef;
}

Desigualdad& Desigualdad::operator=(Desigualdad const& otra)
{
	_isRank = otra._isRank;
	if (otra._soporte != NULL) {
		_soporte = new VertexSet(otra._soporte->capacity());
		_soporte->copyAll(*otra._soporte);
	}
	else
		_soporte = NULL;
	if (otra._coef != NULL) {
		_coef = new IntValueArray(otra._coef->capacity());
		_coef->copy(*otra._coef);
	}
	else
		_coef = NULL;

	return *this;
}

Desigualdad& Desigualdad::operator=(Desigualdad&& otra)
{
	_isRank = otra._isRank;
	if (otra._soporte != NULL) {
		_soporte = new VertexSet(otra._soporte->capacity());
		_soporte->copyAll(*otra._soporte);
	}
	else
		_soporte = NULL;
	if (otra._coef != NULL) {
		_coef = new IntValueArray(otra._coef->capacity());
		_coef->copy(*otra._coef);
	}
	else
		_coef = NULL;

	return *this;
}

void Desigualdad::setAsRank()
{
	_isRank = true;
}

void Desigualdad::setAsNotRank()
{
	_isRank = false;
}

bool Desigualdad::isRank()
{
	return _isRank;
}

int Desigualdad::getCoeficiente(int i)
{
	return (*_coef)[i];
}

void Desigualdad::setCoeficiente(int i, int coef)
{
	_coef->setValue(i, coef);
	_soporte->add(i);
}

bool Desigualdad::esValida(Grafo &g)
{
	RDCliquer cliquer(g, false);
	ProjectableCliqueSet clique(g.getN());
	int ret = cliquer.optimize(*_coef, *_soporte, clique);
	if (ret > getRHS())
	{
		cout << "Maximum stable set: " << ret;
		clique.print();
		Lista l = clique.lista();
		for (int i = 0; i < l.cantidad(); i++)
			for (int j = i + 1; j < l.cantidad(); j++)
				if (g.isArista(l[i], l[j]))
				{
					cout << l[i] << "," << l[j] << " es una arista\n";
					g.vecinos(l[i]).print();
					if (g.isArista(l[j], l[i]))
					{
						cout << l[j] << "," << l[i] << " es una arista\n";
						g.vecinos(l[j]).print();
					}
					exit(0);
				}
	}
	return ret <= getRHS();
}

void Desigualdad::resize(int nv, int nx)
{
	if (_coef == NULL || nx > _coef-> capacity()) {
		IntValueArray * auxc = new IntValueArray(nx);
		if (_coef != NULL) {
			auxc->copy(*_coef);
			delete _coef;
		}
		_coef = auxc;
	}
	if (_soporte == NULL || nv > _soporte-> capacity()) {
		VertexSet * auxv = new VertexSet(nv);
		if (_soporte != NULL) {
			auxv->copyAll(*_soporte);
			delete _soporte;
		}
		_soporte = auxv;
	}
}

double Desigualdad::valor(Solucion& solucion)
{
	double valor = 0.0;
	VertexSetIterator iti = getSoporte().begin();
	for (; iti != getSoporte().end(); ++iti)
		valor += getCoeficiente(*iti) * solucion[*iti];
	return valor;
}

bool Desigualdad::estaViolada(Solucion& solucion, double violacionMinima)
{
	return (valor(solucion) >= (double) getRHS() * (1.0+violacionMinima)) || (valor(solucion) - (double) getRHS() >= 2.0);
}


